package
{
	import AStar.Node;
	
	import UI.*;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.LoaderInfo;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.errors.EOFError;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.TimerEvent;
	import flash.filters.DropShadowFilter;
	import flash.filters.GlowFilter;
	import flash.geom.Point;
	import flash.net.FileReference;
	import flash.net.Socket;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.system.Security;
	import flash.text.TextField;
	import flash.ui.Mouse;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;
	import flash.utils.Endian;
	import flash.utils.Timer;
	import flash.utils.getTimer;
	
	public class GameMain extends Sprite
	{
		private var myCursor:Sprite;
		private var cur1:Bitmap;
		private var cur2:Bitmap;
		
		private var player:Player;
		private var scene:Scene;
	
			
		private var ui:Sprite = new Sprite();
		
		private var myFrame:UIFrame;
		private var AddButton:UIButton;  
		private var ClrButton:UIButton;
		private var ShowMeshCheck:UICheck;
		private var SetBlockCheck:UICheck;
		private var HideBlockCheck:UICheck;			
		private var SaveBlockButton:UIButton;	
		private var BorderLimitCheck:UICheck;
		private var SetAlphaCheck:UICheck;		
		
		
		private var playerMap:Dictionary = new Dictionary();
		
		private var lastHandleDeptTime:int = 0;
		
		private var uiMgr:UIManager = new UIManager();
		
		private var lastMouseClick:int = 0;
		
		private var coords:TextField;
		
		private var output:UITextArea;		
		private var output_showtime:int = 0;
		
		private var chatWindow:UIFrame;
		private var chatContent:UITextArea;
		private var chatInput:UIEdit;
		private var chatSubmit:UIButton;		
		
		private var bCustomCursor:Boolean = false;
		
		private var socket:Socket;
		private var bAreadyReadHeader:Boolean = false;
		private var curPacketLen:int = 0;
		
		private var stg_:Stage;
		
		public function GameMain(stg:Stage)
		{
			stg_ = stg;
			init(stg);			
		}
		
		private function init(stg:Stage):void
		{	
			uiMgr.Init(this);
			
			myFrame = new UIFrame;
			myFrame.Create(20, 20, 150, 400);
		
			ShowMeshCheck = new UICheck;
			ShowMeshCheck.Create(20, 20, 100, 30, "显示网格", onShowMeshCheckClicked);			
			
			SetBlockCheck = new UICheck;
			SetBlockCheck.Create(20, 60, 100, 30, "设置阻挡", onSetBlockCheckClicked);		
			
			HideBlockCheck = new UICheck;
			HideBlockCheck.Create(20, 100, 100, 30, "隐藏阻挡", onHideBlockCheckClicked);				
	
			SetAlphaCheck = new UICheck;
			SetAlphaCheck.Create(20, 140, 100, 30, "设置虚化", onSetAlphaCheckClicked);			
			
			BorderLimitCheck = new UICheck;
			BorderLimitCheck.Create(20, 180, 100, 30, "不限边界", onBorderLimitCheckClicked);			
			
			SaveBlockButton = new UIButton;
			SaveBlockButton.Create(20, 220, 100, 30, "保存", onSaveBlockButtonClicked);				
			
			stg.showDefaultContextMenu = false;
			stg.scaleMode = StageScaleMode.NO_SCALE;
			stg.align=StageAlign.TOP_LEFT;

			scene = new Scene(stg);
			addChild(scene);
			//scene.x = 150;
					
			addEventListener(Event.ENTER_FRAME, onEnterFrame);		
			addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);			
			addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);	
			
			//监听主角移动事件
			stg.addEventListener(GameEvent.HERO_MOVE, onHeroMove)
			
			//stage.addEventListener(Event.FULLSCREEN, onResize);			
			
			stg.addEventListener(Event.RESIZE, onMyResize);	
			
			stg.addEventListener(GameEvent.HERO_SET_FOCUS, onHeroSetFocus) 
				
			myFrame.addChild(ShowMeshCheck);
			myFrame.addChild(SetBlockCheck);
			myFrame.addChild(HideBlockCheck);
			myFrame.addChild(SetAlphaCheck);			
			myFrame.addChild(SaveBlockButton);
			myFrame.addChild(BorderLimitCheck);
			//addChild(myFrame);
			
			//右上角坐标提示
			coords = new TextField();
			coords.textColor = 0xFFFF00;
			coords.x = 100;
			coords.y = 100;
			coords.selectable = false;
			coords.cacheAsBitmap = true;	
			coords.filters = [new GlowFilter(0x000000,1,1.2,1.2,100)];
			addChild(coords);			
		
			//右下角信息提示
			output = new UITextArea();
			addChild(output);			
	
			//聊天框
			//private var chatWindow:UIFrame;
			//private var chatContent:UITextArea;
			//private var chatInput:UIEdit;		
			chatWindow = new UIFrame();
			chatWindow.Create(20, 500, 200, 150);
			
			chatContent = new UITextArea(200, 150);
			chatWindow.addChild(chatContent);
			
			//chatInput = new UIEdit;
			//chatInput.Create(20,650, 100, 20, null);
			//chatInput.addEventListener(KeyboardEvent.KEY_DOWN, onEditKeyDown);
			
			addChild(chatWindow);
			//addChild(chatInput);
			
			chatSubmit = new UIButton;
			chatSubmit.Create(125, 650, 60, 20, "说话", onChatSubmit);
			addChild(chatSubmit);
			
			//加载阻挡点
			LoadBlocks();
			
			//光标
			cur1 = new Bitmap((new ResourceMgr.Cursor1() as Bitmap).bitmapData);
			cur2 = new Bitmap((new ResourceMgr.Cursor2() as Bitmap).bitmapData);
			myCursor = new Sprite();
			myCursor.addChild(cur1);
			
			var tmrLoadScene:Timer = new Timer(100, 1);
			tmrLoadScene.addEventListener(TimerEvent.TIMER, onTimerLoadScene);
			tmrLoadScene.start();
		

			//Security.allowDomain("*");
			//Security.loadPolicyFile("xmlsocket://192.168.7.50:844");

			//socket连接
			socket = new Socket();

			socket.endian = Endian.LITTLE_ENDIAN;
			socket.addEventListener(ProgressEvent.SOCKET_DATA, onData);
			socket.addEventListener(Event.CONNECT, onConnect);
			socket.addEventListener(Event.CLOSE, onClose);				
			socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
		
			//socket.connect("192.168.7.50", 8888);
			addDemoPlayer();
		}
	
		private function addDemoPlayer():void
		{
			player =  new Player(stg_, "玩家", new Point(700 , 600), true);
			player.name = "玩家";
			player.roleID = 0;
			
			scene.sceneRoot.addChild(player);
			scene.viewPoint = new Point(player.curX, player.curY);			
			addChildAt(scene, 0);
			
			scene.Load();
		}
		
		private function onSecurityError(evt:SecurityErrorEvent):void {
			output.addLine("无法连接服务器");
			output.width = 100;
			output_showtime = getTimer();
		}		
	
		private function onClose(evt:Event):void 
		{
			//output.addLine("与服务器断开连接！");
			//output_showtime = getTimer();	
			
		}
		
		private function onConnect(evt:Event):void 
		{
			output.addLine("连接服务器成功！");
			output_showtime = getTimer();	
			
			//获取PlayerID
			socket.writeShort(0xFFFF);
			socket.writeInt(10);
			socket.writeInt(GameGlobals.NET_DATA_GET_PLAYER_ID);
			socket.flush();
		}		
		
		private function notifyPlayerInfo(_player:Player):void
		{
			if(!socket.connected)
				return;
			
			socket.writeShort(0xFFFF);
			socket.writeInt(22);
			socket.writeInt(GameGlobals.NET_DATA_PLAYER_INFO);
			socket.writeInt(_player.roleID);
			socket.writeInt(Math.floor(_player.curX/Scene.gridWidth))
			socket.writeInt(Math.floor(_player.curY/Scene.gridHeight))	
			socket.flush();				
		}
		
		//private function onEditKeyDown(e:KeyboardEvent):void
		//{
		//	if(e.keyCode == Keyboard.ENTER)
		//	{
		//		onChatSubmit();
		//	}
		//}
		
		private function onChatSubmit():void
		{
			if(!socket.connected)
			{
				output.addLine("未与服务器连接");
				return;
			}
		
			if(chatInput.mText.text.length == 0)
				return;
			
			var ba:ByteArray = new ByteArray();
			ba.writeUTFBytes(chatInput.mText.text);	
			
			//trace(ba.length);
			//trace(ba);
			
			socket.writeShort(0xFFFF);
			socket.writeInt(ba.length + 14);
			socket.writeInt(GameGlobals.NET_DATA_CHAT);
			socket.writeInt(player.roleID);
			socket.writeBytes(ba);
			socket.flush();
			
			chatInput.mText.text = "";
		}		
	

		private function onData(evt:ProgressEvent):void
		{
			parsePacket();
		}
			 
		// 解析网络数据流   	
		private function parsePacket():void   		
		{   
			const HEAD_LEN:int = 10;
			var header:uint;
			var typeid:int;
			
			if(!bAreadyReadHeader)
			{
				header = socket.readShort(); 
				curPacketLen = socket.readInt();
				typeid = socket.readInt();
				//trace("header:"+header+",len:"+curPacketLen+",type:"+typeid)	
				
				bAreadyReadHeader = true;
			}
			
			if(curPacketLen < HEAD_LEN)
			{
				socket.close();
				trace("数据异常");
				return;
			}
			
			var dataLen:int = curPacketLen - HEAD_LEN;
			
			if(socket.bytesAvailable < dataLen)
			{
				return;
			}
			
			
			var bytes:ByteArray = new ByteArray();
			bytes.endian = Endian.LITTLE_ENDIAN;
			//指针回归   
			bytes.position = 0;   
			
			//取出指定长度的网络字节   
			socket.readBytes(bytes, 0, dataLen);   
			handleData(typeid, bytes, dataLen);		
			
			bAreadyReadHeader = false;
			
			//如果数据流里还满足读取数据条件，继续读取数据  		
			if(socket.bytesAvailable >= HEAD_LEN)   		
			{   	
				trace("++++++++++++++");
				parsePacket();   			
			}   	
		}   
		
	
		
		private function handleData(typeid:int, buf:ByteArray, len:int):void 
		{	
			switch(typeid)
			{
			case GameGlobals.NET_DATA_PLAYER_ID_RET:
				if(player != null)
					return;
				
				var rid:int = buf.readInt();
				
				var rx:Number = Math.floor((Math.random()*100+700)/Scene.gridWidth)*Scene.gridWidth;
				var ry:Number = Math.floor((Math.random()*100+600)/Scene.gridHeight)*Scene.gridHeight;
				
				player =  new Player(stg_, "玩家"+rid, new Point(rx , ry), true);
				player.name = "玩家"+rid;
				player.roleID = rid;
				
				scene.sceneRoot.addChild(player);
				scene.viewPoint = new Point(player.curX, player.curY);			
				addChildAt(scene, 0);
				
				scene.Load();
				
				notifyPlayerInfo(player);
				
				output.addLine("玩家"+rid+"进入游戏");
				
				break;
			case GameGlobals.NET_DATA_NEW_PLAYER_LIST:
				if(player == null)
					return;
				
				var listLen:int = buf.readInt();
				
				for(var i:int = 0; i < listLen; i++)
				{
					var rrid:int = buf.readInt();
					var posX:int = buf.readInt();
					var posY:int = buf.readInt();
					
					if(rrid == player.roleID)
						continue;
					
					if(!isPlayerExist(rrid))
					{
						var otherplayer:Player =  new Player(stg_, "玩家"+rrid, new Point(0, 0), false);
						otherplayer.curX = posX*Scene.gridWidth;
						otherplayer.curY = posY*Scene.gridHeight;
						otherplayer.name = "玩家"+rrid;
						otherplayer.roleID = rrid;
				
						scene.sceneRoot.addChild(otherplayer);	
						AddPlayer(rrid, otherplayer);	
						
						output.addLine("玩家"+rrid+"进入游戏");
					}
					else
					{
						var tmpPlayer:Player = getPlayer(rrid);
						if(tmpPlayer != null && (tmpPlayer.curX != posX*Scene.gridWidth || tmpPlayer.curY != posY*Scene.gridHeight))
						{
							tmpPlayer.MoveTo(posX*Scene.gridWidth, 	posY*Scene.gridHeight);					
						}
						

					}
				}
				break;
			case GameGlobals.NET_DATA_CHAT:
					var roleid:int = buf.readInt();
				
					var ba:ByteArray = new ByteArray(); 
					try
					{	
						buf.readBytes(ba, 0, len-4);	
					}
					catch(e:EOFError)
					{
						output.addLine("读取内容出错");
					}
					
					//trace("back:"+ba);
					chatContent.addLine("玩家"+roleid+":"+ba.toString());	
					
				break;
			case GameGlobals.NET_DATA_PLAYER_OUT:
				var rmPlayer:int = buf.readInt();
				
				output.addLine("玩家"+rmPlayer+"离开游戏");
				
				DelPlayer(rmPlayer);
			
			default:
				break;
			}
			
		}		

		
		
		private function LoadBlocks():void
		{
			var xmlLoader:URLLoader = new URLLoader();
			xmlLoader.addEventListener(Event.COMPLETE, xmlLoadComplete);
			xmlLoader.load(new URLRequest("block.xml"));		
		}
		
		private function xmlLoadComplete(event:Event):void
		{	
			var xmlBlock:XML = new XML((event.target as URLLoader).data);
			var str:String = xmlBlock.Blocks;
			//trace(str);
			
			var blks:Array = new Array();
			var tmp:Array = str.split(" ");
			for each (var s:String in tmp)
			{
				var xy:Array = s.split(",");
				if(xy == null || xy.length != 2)
					continue;
			
				//trace(xy);
				blks.push(new Point(xy[0], xy[1]))
			}
		
			scene.setBlocks(blks);			
			
			str = xmlBlock.Alphas;
			var alps:Array = new Array();
			var tmpA:Array = str.split(" ");
			for each (var sa:String in tmpA)
			{
				var xyA:Array = sa.split(",");
				if(xyA == null || xyA.length != 2)
					continue;
				
				//trace(xyA);
				alps.push(new Point(xyA[0], xyA[1]))
			}	
			
			scene.setAlphas(alps);

		}	
		
		private function isPlayerExist(roleID:int):Boolean
		{
			return (playerMap[roleID]!=null);
		}
		
		private function getPlayer(roleID:int):Player
		{
			return playerMap[roleID];
		}
		
		private function AddPlayer(roleID:int, _player:Player):void
		{	
			playerMap[roleID] = _player;
		}
	
		private function DelPlayer(roleID:int):void
		{	
			if(playerMap[roleID] == null)
				return;
			
			scene.sceneRoot.removeChild(playerMap[roleID]);
			(playerMap[roleID] as Player).unInit();
			
			playerMap[roleID] = null;
			
		}		
		
		private function onShowMeshCheckClicked():void
		{
			if(ShowMeshCheck.mChecked)
				scene.showMesh();
			else
				scene.hideMesh();
		}	
	
		private function onSetBlockCheckClicked():void
		{
			if(SetBlockCheck.mChecked)
			{
				scene.showBlocks();
				scene.bSetBlock = true;
			}
			else	
				scene.bSetBlock = false;	
		}		
	
		private function onHideBlockCheckClicked():void
		{
			if(HideBlockCheck.mChecked)
			{
				scene.hideBlocks();
				scene.hideAlphas();
			}
			else
			{
				scene.showBlocks();
				scene.showAlphas();
			}

		}	
	
		private function onSetAlphaCheckClicked():void
		{
			if(SetAlphaCheck.mChecked)
				scene.bSetAlpha = true;
			else
				scene.bSetAlpha = false;
		}		
		
		
	
		private function onBorderLimitCheckClicked():void
		{
			if(BorderLimitCheck.mChecked)
				scene.bBorderLimit = false;
			else
				scene.bBorderLimit = true;
		}		
		
		
		private function onSaveBlockButtonClicked():void
		{
			var blks:Array = scene.getBlocks();
			var aplhas:Array = scene.getAlphas();
			
			var xmlBlock:XML = <Map/>;
			
			var str:String = "";
			for each (var pt:Point in blks)
			{
				str += " "+pt.x + "," + pt.y;
			}
			
			xmlBlock.Blocks = str;
			//trace(xmlBlock)
			
			str= "";
			for each (pt in aplhas)
			{
				str += " "+pt.x + "," + pt.y;
			}
			
			xmlBlock.Alphas = str;	
			
			var fileref:FileReference = new FileReference();
			fileref.save(xmlBlock, "block.xml");
		}	
		
		private function onMyResize(event:Event):void
		{
			scene.Load();			
			
			return;

		}
		
		private function onTimerLoadScene(e:TimerEvent):void
		{
			scene.Load();
		}		
		
		private function onHeroMove(e:GameEvent):void
		{
			if(scene.isAlpha(e.posX, e.posY))
			{
				player.alpha = 0.5;
			}
			else
			{
				player.alpha = 1.0;
			}
			
			if(player != null)
				notifyPlayerInfo(player);
		}
		
		private function swapPlayer(player1:Player, player2:Player):void
		{
			var rg1:Region = new Region(player1.x, player1.y, player2.x+150, player2.y+150);
			var rg2:Region = new Region(player1.x, player1.y, player2.x+150, player2.y+150);
			
			if(rg1.isCrossWithRegion(rg2))
			{
				var idx1:int = scene.sceneRoot.getChildIndex(player1);
				var idx2:int = scene.sceneRoot.getChildIndex(player2);
				
				//trace("idx1: "+idx1+",idx2: "+idx2+" y1: "+player1.y+",y2: "+player2.y)
				
				
				if((idx2 < idx1 && player2.y > player1.y) || (idx1 < idx2 && player1.y > player2.y))
				{
					//trace(player1.name)
					//trace(player2.name)
					scene.sceneRoot.swapChildren(player1, player2);
				}
			}		
		}
		
		
		private function handleDepth():void
		{
			var playerArray:Array = new Array();
			for each(var p:Player in playerMap)
			{
				if(p!=null)
					playerArray.push(p);
			}
			
			for(var i:int = 0; i < playerArray.length; i++)
			{
				swapPlayer(playerArray[i], player);
				for(var j:int = i+1; j < playerArray.length; j++)
				{	
					swapPlayer(playerArray[i], playerArray[j]);
				}
			}		
		}
		
		private function onEnterFrame(event:Event):void
		{
			var curTime:int = getTimer();
			
			if(curTime - lastHandleDeptTime >= 300)
			{
				handleDepth();
				lastHandleDeptTime = curTime;
			}
				
			//显示坐标
			if(player !=null )
			{
				coords.text = "坐标 x:"+Math.floor(player.curX)+",y:"+Math.floor(player.curY);
				coords.x = stg_.stageWidth - 100;
				coords.y = 20;
			}

			
			output.x = stg_.stageWidth -150;
			output.y = stg_.stageHeight - 200;		
			
			chatWindow.y = stg_.stageHeight - 200;
			//chatInput.y = stg_.stageHeight - 50;
			chatSubmit.y = stg_.stageHeight - 50;
			
			//trace(stage.stageWidth);
			//trace(stage.stageHeight);
		}
		
		private function mouseMoveHandler(event:MouseEvent):void
		{
			if(bCustomCursor)			
			{
				Mouse.hide();
				
				myCursor.x = getMouseX();
				myCursor.y = getMouseY();
				
				if(myCursor.parent != this)
				{
					scene.sceneRoot.addChild(myCursor);
				}
				
				event.updateAfterEvent();		
			}
			/*if(mouseDownClickTime < 0)
			{
			return;
			}
			
			if(mouseDownClickTime == 0)
			{
			mouseDownClickTime = getTimer();
			}
			
			if(getTimer() - mouseDownClickTime >= 500 || getTimer() - mouseDownClickTime == 0)
			{
			destX = getMouseX();
			destY = getMouseY();
			
			MoveTo(destX, destY);
			
			mouseDownClickTime = getTimer();
			}*/
		}		
		
		private function getMouseX():Number
		{
			return mouseX - scene.sceneRoot.x;
		}
		
		private function getMouseY():Number
		{
			return mouseY - scene.sceneRoot.y;
		}		
		
		private function mouseUpHandler(event:MouseEvent):void
		{
			if(bCustomCursor)
			{
				if(cur2.parent == myCursor)			
					myCursor.removeChild(cur2);
				
				if(cur1.parent != myCursor)
					myCursor.addChild(cur1);	
				
				event.updateAfterEvent();			
			}
		}
		
		private function PlayerMoveTo(p:Player, x:Number, y:Number):void
		{
			if(scene.isBlocked(getMouseX(), getMouseY()))
			{
				output.addLine("该地点无法到达");
				output_showtime = getTimer();
				return;
			}			
			
			scene.setStartPoint(p.curX, p.curY);
			scene.setEndPoint(x, y);
			var path:Array = scene.findPath();
			
			for each (var pt:Node in path)
			//trace("x "+pt.x +", y "+ pt.y);
			p.setPath(path);
		}
		
		private function mouseDownHandler(event:MouseEvent):void
		{
			if(bCustomCursor)
			{
				if(cur1.parent == myCursor)			
					myCursor.removeChild(cur1);
				
				if(cur2.parent != myCursor)
					myCursor.addChild(cur2);
				
				event.updateAfterEvent();				
			}
		
			if(SetBlockCheck.mChecked || SetAlphaCheck.mChecked)
				return;
		
			var curTime:int = getTimer();
			if(curTime - lastMouseClick > 200)
			{
				PlayerMoveTo(player, getMouseX(), getMouseY());
				
				lastMouseClick = curTime;
			}
			
			var playerArray:Array = new Array();
			for each(var p:Player in playerMap)
			{
				if(p!=null)
					playerArray.push(p);
			}
			
			for(var i:int = 0; i < playerArray.length; i++)
			{
				var tmpPlayer:Player = playerArray[i] as Player;
				
				if(tmpPlayer != null && tmpPlayer.isOnFocus())
				{	
					tmpPlayer.loseFocus();			
				}
			}		
		}
		
		private function onHeroSetFocus(event:GameEvent):void
		{
			var fcsPlayer:Player = (event.player as Player);
			if(fcsPlayer != null)
			{
				var playerArray:Array = new Array();
				for each(var p:Player in playerMap)
				{
					if(p!=null)
						playerArray.push(p);
				}
				
				for(var i:int = 0; i < playerArray.length; i++)
				{
					var tmpPlayer:Player = playerArray[i] as Player;
					
					if(tmpPlayer !== (event.player as Player) && tmpPlayer.isOnFocus())
					{
						//trace(tmpPlayer.name)
						//trace(event.player.name)
						
						tmpPlayer.loseFocus();			
					}
				}
			}
		}
			
	}
}